
#import "GameManager.h"

int W=320;
int H=480;

@implementation GameManager

#pragma mark ============================= Init Methods ================================

+ (GameManager*) getInstance  {
    
    static GameManager* gameManager;
		
	if (!gameManager) {
        gameManager = [[GameManager alloc] init];
		[gameManager preloader];            
	}
	    
    return gameManager;
}

- (void) preloader {        
    touchedY = 0;
    [self setOGLProjection];    
    state = LOAD_GAME;
}

- (void) loadGame { 
}

#pragma mark ============================= Game Handler ===============================

- (void) touchBegan: (CGPoint) p {      
//    NSLog(@"Touch: %f %f", p.x, p.y);
    float x = p.x - W/2;
    float y = 0.0001 * x*x*x;
    touchedY = y;
    NSLog(@"touchedY: %f", y);
}

- (void) touchMoved: (CGPoint) p {
    [self touchBegan: p];      
}

- (void) touchEnded {
}

- (void) drawStatesWithFrame: (CGRect) frame { 
    W = frame.size.width;
    H = frame.size.height; 
    switch (state) {
        case LOAD_GAME: 
            [self loadGame];
            state = PLAY_GAME;
            break;  
        case PLAY_GAME:
            [self playGame];
            break;           
        default: NSLog(@"ERROR: Unknown state: %i", state);
            break;
    }    
}	 

- (void) playGame {
    timer++;              
    [self draw2DGraphPlotter];
    //Add by Thomas DrawText －－－start
    [self drawOGLTextInPoint:CGPointMake(10, 20) WithText:[NSString stringWithFormat:@"Y:%.2f",touchedY]];
    //Add by Thomas DrawText －－－end
} 

#pragma mark ============================= OGL Methods ===============================

- (void) setOGLProjection {    
    //Set View
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity();    
    
    //设置顶点
    //glOrthof (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar);//忽略zNear、zFar将其设为默认值0和1
    glOrthof(-W/2, W/2, -H/2, H/2, 0, 1);
//    glOrthof(0, W, H, 0, 0, 1);
    
    glMatrixMode(GL_MODELVIEW);
    glEnableClientState(GL_VERTEX_ARRAY); 
    glDisable(GL_DEPTH_TEST); //2D only 
} 

- (void) draw2DGraphPlotter {    
    //因setOGLProjection中glOrthof方法调整了坐标系
    [self drawOGLLineFrom: CGPointMake(W/2, 0) to: CGPointMake(-W/2, 0)];
    [self drawOGLLineFrom: CGPointMake(0, H/2) to: CGPointMake(0, -H/2)]; 

    for (float x = -W/2; x < W/2; x += 0.01) { 
        
        float y = 0.0001 * x*x*x;
//        float y = 10*sin(x);
        
        GLfloat point[ ] = { 
            x, y    
        };
        
        glVertexPointer(2, GL_FLOAT, 0, point);
        glDrawArrays(GL_POINTS, 0, 1);        
    }
}

- (void) drawOGLLineFrom: (CGPoint) p1 to: (CGPoint) p2 {
    GLshort vertices[ ] = { 
        p1.x, p1.y,
        p2.x, p2.y        
    };      

    glVertexPointer(2, GL_SHORT, 0, vertices);           
    glColor4f(1, 1, 0, 1);
    glDrawArrays(GL_LINES, 0, 2);       
}

//Add by Thomas DrawText －－－start
- (void) drawOGLTextInPoint:(CGPoint)point WithText:(NSString *)text{
    [self createTexFromString:text];
    [self drawAt:point];
}

- (void) drawAt: (CGPoint) p {
    GLshort imageVertices[ ] = {
        0,      height,
        width,  height,
        0,      0,
        width,  0
    };
    
    GLshort textureCoords[ ] = {
        0, 1,
        1, 1,
        0, 0,
        1, 0
    };
    
    //p.x = (int) p.x;
    //p.y = (int) p.y;
    
    glEnable(GL_TEXTURE_2D);
    
    glColor4f(1, 1, 1, 1);
    glBindTexture(GL_TEXTURE_2D, textureID);
    glVertexPointer(2, GL_SHORT, 0, imageVertices);
    glTexCoordPointer(2, GL_SHORT, 0, textureCoords);
    
    glPushMatrix();
    glTranslatef(p.x, p.y, 0);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glPopMatrix();
    
    glDisable(GL_TEXTURE_2D);
}

- (void) createTexFromString: (NSString *) text{
    int len = [text length]*20;
    if (len < 64) width = 64;
    else if (len < 128) width = 128;
    else if (len < 256) width = 256;
    else width = 512; //max width text
    height = 32;
    
    GLubyte *pixelData = [self generatePixelDataFromString: text];
    
    [self generateTexture: pixelData];
    free(pixelData);
}

- (void) generateTexture: (GLubyte *) pixelData {
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelData);
    
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}

- (GLubyte *) generatePixelDataFromString: (NSString *) text {
    const char *cText = [text cStringUsingEncoding: NSASCIIStringEncoding];
    GLubyte *pixelData = (GLubyte *) calloc( width*height*4, sizeof(GLubyte) );
    CGColorSpaceRef rgbCS = CGColorSpaceCreateDeviceRGB();
    CGContextRef gc = CGBitmapContextCreate( pixelData,
                                            width, height, 8, width*4,
                                            rgbCS,
                                            kCGImageAlphaPremultipliedLast);
    int size = 22;
    CGContextSetRGBFillColor(gc, 0,1,0,1);
    CGContextSelectFont(gc, "Verdana", size, kCGEncodingMacRoman);
    int ys = height-size; //swapped y-axis
    CGContextShowTextAtPoint(gc, 0, ys, cText, strlen(cText));
    CGColorSpaceRelease(rgbCS);
    CGContextRelease(gc);
    return pixelData;
}

//Add by Thomas DrawText －－－end

- (void) drawOGLRect: (CGRect) rect {
    GLshort vertices[ ] = {
        0,                  rect.size.height, 
        rect.size.width,    rect.size.height, 
        0,                  0, 
        rect.size.width,    0  
    };
        
    glVertexPointer(2, GL_SHORT, 0, vertices);           
    glColor4f(1, 1, 0, 1);
    
    glPushMatrix();      
    glTranslatef(rect.origin.x, rect.origin.y, 0);          
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 
    glPopMatrix();      
}

#pragma mark ============================= Helper Methods ===============================

- (void) setState: (int) stt {
    state = stt;
}

- (int) getRndBetween: (int) bottom and: (int) top {		
	int rnd = bottom + (arc4random() % (top+1-bottom)); 
	return rnd;
} 

- (void) dealloc {        
    [super dealloc];
}

@end
